// ------------------------------------------------------------------------------------------------
// File   : DX9PixelShader.h
// Date   : 2012-08-01
// Author : Weng xiao yi
// Rev.   : 
// Descr. : 
// ------------------------------------------------------------------------------------------------

#ifndef OY_DX9PIXELSHADER_H
#define OY_DX9PIXELSHADER_H

#include "DX9Shader.h"

// pixel shader definition ----------------------------------------

enum FDX9PSGlobalConstant 
{
	PS_GLOBAL_CONSTANT_MISC_FLOAT,
	PS_GLOBAL_CONSTANT_MISC_VECTOR,



	PS_GLOBAL_CONSTANT_COLOR,
	PS_CLOBAL_CONSTANT_WATER_BUMPFRESNEL,
	PS_GLOBAL_CONSTANT_WATER_BLEND,

	PS_GLOBAL_CONSTANT_HIGHLIGHTTHRESHOLD,
	PS_GLOBAL_CONSTANT_SCENEINTENSITY,
	PS_GLOBAL_CONSTANT_GLOWINTENSITY,
	PS_GLOBAL_CONSTANT_HIGHLIGHTINTENSITY,

	PS_GLOBAL_CONSTANT_FOG_INVWVPMATRIX,
	PS_GLOBAL_CONSTANT_FOG_CAMERAPOS,
	PS_GLOBAL_CONSTANT_FOG_LAYERMINMAX,
	PS_GLOBAL_CONSTANT_FOG_COLOR,
	PS_GLOBAL_CONSTANT_FOG_COLORTOP,
	PS_GLOBAL_CONSTANT_FOG_COLORBOTTOM,

	
	PS_GLOBAL_CONSTANT_DOF_KERNELARRAY,
	PS_GLOBAL_CONSTANT_DOF_RADIUSSCALE,

	PS_GLOBAL_CONSTANT_SCREENRESOLUTION,

	PS_GLOBAL_CONSTANT_GAMMA_SCALE,

	PS_GLOBAL_CONSTANT_SOFTPRATICLE_SCALE,
	PS_GLOBAL_CONSTANT_SOFTPRATICLE_CONTRAST,

	PS_GLOBAL_CONSTANT_COUNT
};

// pixel shader global constant HLSL names
const char g_aszPSGlobalConstName[PS_GLOBAL_CONSTANT_COUNT][32] = {
	"g_fMiscFloat",						// PS_GLOBAL_CONSTANT_MISC_FLOAT
	"g_fMiscVector",					// PS_GLOBAL_CONSTANT_MISC_VECTOR


	"g_vConstantColor",					// PS_GLOBAL_CONSTANT_COLOR
	"g_vWaterBumpFresnel",				// PS_CLOBAL_CONSTANT_WATER_BUMPFRESNEL
	"g_vWaterDepthBlend",				//PS_GLOBAL_CONSTANT_WATER_BLEND

	"g_fHighLightThreshold",			// PS_GLOBAL_CONSTANT_HIGHLIGHTTHRESHOLD
	"g_fSceneIntensity",				// PS_GLOBAL_CONSTANT_SCENEINTENSITY
	"g_fGlowIntensity",					// PS_GLOBAL_CONSTANT_GLOWINTENSITY
	"g_fHighLightIntensity",			// PS_GLOBAL_CONSTANT_HIGHLIGHTINTENSITY

	"g_mInvWorldViewProj",				// PS_GLOBAL_CONSTANT_FOG_INVWVPMATRIX,
	"g_fCameraPos",						// PS_GLOBAL_CONSTANT_FOG_CAMERAPOS,
	"g_fFogLayerMinMax",				// PS_GLOBAL_CONSTANT_FOG_LAYERMINMAX,
	"g_fFogColorWithDensity",			// PS_GLOBAL_CONSTANT_FOG_COLOR,
	"g_fFogColorTop",					// PS_GLOBAL_CONSTANT_FOG_COLORTOP,
	"g_fFogColorBottom",				// PS_GLOBAL_CONSTANT_FOG_COLORBOTTOM,

	"g_KernelArray",					// PS_GLOBAL_CONSTANT_DOF_KERNELARRAY,
	"g_BlurRadiusScale",				// PS_GLOBAL_CONSTANT_DOF_RADIUSSCALE

	"g_vScreenResolutionPS",			// PS_GLOBAL_CONSTANT_SCREENRESOLUTION

	"g_fGammaScale",					// PS_GLOBAL_CONSTANT_GAMMA_SCALE

	"g_SoftParticleScale",				// PS_GLOBAL_CONSTANT_SOFTPRATICLE_SCALE
	"g_SoftParticleContrast",			// PS_GLOBAL_CONSTANT_SOFTPRATICLE_CONTRAST
};

class DX9PixelShader : public DX9Shader<LPDIRECT3DPIXELSHADER9 , PS_GLOBAL_CONSTANT_COUNT>
{
public:

	inline BOOL ReInit(const DWORD *_pShaderStream, BOOL bAssembleShader = FALSE);

	inline DX9PixelShader*  Duplicate(void) const;
};


inline BOOL DX9PixelShader::ReInit(const DWORD *_pShaderStream, BOOL bAssembleShader)
{
	HRESULT hr;

	// create shader interface
	hr = GetD3DDevice()->CreatePixelShader( _pShaderStream, &m_pShaderInterface );
	//DX9ValidateRet(SUCCEEDED(hr), FALSE, "Device pixel shader creation failed");

	if (bAssembleShader && m_pConstantTable == NULL)
		return TRUE;

	if (m_pConstantTable == NULL)
	{
		// get constant table
		hr = D3DXGetShaderConstantTable(_pShaderStream, &m_pConstantTable);
		if (FAILED(hr))
		{
			// destroy shader interface
			DX9_SAFE_RELEASE(m_pShaderInterface);
			DX9_SAFE_RELEASE(m_pConstantTable);

			return FALSE;
			//DX9ValidateRet(SUCCEEDED(hr), FALSE, "Unable to access a pixel shader's constant table");
		}
	}

	// get all global constant handles
	for (ULONG ulCurGlobalConst = 0; ulCurGlobalConst < PS_GLOBAL_CONSTANT_COUNT; ulCurGlobalConst++)
	{
		m_ahConstant[ulCurGlobalConst] = m_pConstantTable->GetConstantByName(NULL, g_aszPSGlobalConstName[ulCurGlobalConst]);

		if( m_ahConstant[ulCurGlobalConst] )
		{
			D3DXCONSTANT_DESC oDesc;
			UINT uiCount=1;
			hr = m_pConstantTable->GetConstantDesc(m_ahConstant[ulCurGlobalConst], &oDesc, &uiCount);
			DX9Verify( SUCCEEDED(hr) );
			m_lRegister[ulCurGlobalConst] = oDesc.RegisterIndex;
		}
		else
		{
			m_lRegister[ulCurGlobalConst] = -1;
		}
	}

	return TRUE;
}

inline DX9PixelShader* DX9PixelShader::Duplicate(void) const
{
	DX9PixelShader* pNewShader = new DX9PixelShader();

	pNewShader->m_pShaderInterface = m_pShaderInterface;
	pNewShader->m_pConstantTable   = m_pConstantTable;
	pNewShader->m_bAutoGenerated   = m_bAutoGenerated;

	memcpy(pNewShader->m_ahConstant, m_ahConstant, PS_GLOBAL_CONSTANT_COUNT * sizeof(D3DXHANDLE));
	memcpy(pNewShader->m_lRegister,  m_lRegister,  PS_GLOBAL_CONSTANT_COUNT * sizeof(LONG));

	if (pNewShader->m_pShaderInterface != NULL)
	{
		pNewShader->m_pShaderInterface->AddRef();
	}

	if (pNewShader->m_pConstantTable != NULL)
	{
		pNewShader->m_pConstantTable->AddRef();
	}

#if defined(SHADER_DEBUG)
	strcpy_s(pNewShader->m_Filename, m_Filename);
#endif

	pNewShader->m_bIsDefault = m_bIsDefault;

	return pNewShader;
}

#endif // OY_DX9PIXELSHADER_H
